/* 
 * File:   Escenario.cpp
 * Author: 75.02 - Grupo 7, 2do cuatrimestre 2012.
 * 
 * Created on 31 de octubre de 2012, 18:47
 */

#include <vector>

#include "Escenario.h"
using namespace TP::Juego::Arena;

Escenario::Escenario(){}

Escenario::Escenario(unsigned pAlto, unsigned pAncho, const string &rutaImagenFondo) {

    this->_perimetro = new Perimetro(pAlto, pAncho);
    _ruta_image_fondo = rutaImagenFondo;

    /* @todo: aca carga la imagen, o lo hace el drawing area del cliente?.
     * Me parece que lo tiene que hacer el cliente */
}

Escenario::~Escenario() {
	
    delete this->_perimetro;
    for (unsigned int i = 0; i < _actores.size(); ++i) {
            delete _actores[i];
    }
    for (unsigned int i = 0; i < _utilidades.size(); ++i) {
            delete _utilidades[i];
    }
}

// Recibe punteros creados con new */

Actor* Escenario::addActor(Actor* pActor, Posicion* pPosicion, Vector2D* pVelocidad, Vector2D* pAceleracion) {

	if (pActor && pPosicion && pVelocidad) {
		/* Construyo la trayectoria que debe tener el actor dentro de la arena
		 * de juego.
		 */
		Trayectoria* trayectoria = new Trayectoria(pPosicion, pVelocidad, pAceleracion);

		if (trayectoria) {
			// Le asigno la trayectoria al actor.
			pActor->setTrayectoria(trayectoria);

			// Agrego al actor a la arena de juego.
			this->_actores.push_back(pActor);
		}
	}

	return pActor;
}

Actor* Escenario::getActorPorNombre(const string& pNombreActor) {

	Actor* actorReturn = NULL;

	for (int cur = 0; cur < this->_actores.size(); cur++) {
		if (pNombreActor == this->_actores[cur]->Nombre()) {
			actorReturn = this->_actores[cur];
			break;
		}
	}
	return actorReturn;
}

vector<Actor*>& Escenario::getActores() {
	return this->_actores;
}

Utilidad* Escenario::addUtilidad(Utilidad* pUtilidad, Posicion* pPosicion) {

	if (pUtilidad && pPosicion) {
		pUtilidad->setPosicion(pPosicion);
		this->_utilidades.push_back(pUtilidad);
	}
	return pUtilidad;
}

vector<Utilidad*>& Escenario::getUtilidades() {
	return this->_utilidades;
}

Perimetro* Escenario::getPerimetro() {
	return this->_perimetro;
}

vector<struct InfoMov*>& Escenario::getSemillasGeneradorPajaritos (){
    return this->_semillasGeneradorPajaritos;
}

struct InfoMov* Escenario::setSemillaGeneradorPajaritos(struct InfoMov* pSemilla){
    this->_semillasGeneradorPajaritos.push_back(pSemilla);
}

const string& Escenario::getRutaImagenFondo() const {
	return _ruta_image_fondo;
}

void Escenario::liberar(){
    
    // Elimino los actores del escenario liberando los recursos.
    for (int cur = 0; cur < this->_actores.size(); cur++)
        delete this->_actores[cur];
    
    this->_actores.clear();
    

    // Elimino las utilidades del Escenario liberando los recursos.
    for (int cur = 0; cur < this->_utilidades.size(); cur++)
        delete this->_utilidades[cur];
    
    this->_utilidades.clear();
}

string Escenario::aXML(){

    TiXmlDocument* doc = new TiXmlDocument();
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());

    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

string Escenario::aXML(const string& pPath){

    TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());
    
    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

void Escenario::parseXML (const string& pDescriptor){

    TiXmlDocument doc;
    doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
    this->deElementoXML(doc.FirstChildElement());
}

TiXmlElement* Escenario::aElementoXML (){
    
    TiXmlElement * escenarioXML = new TiXmlElement("Escenario");

    /* Elementos a serializar.
     
    string _ruta_image_fondo;
    vector<Actor*> _actores;
    vector<Utilidad*> _utilidades;
    Perimetro* _perimetro;
    
     */
    
    // Serializo el path a la imagen de fondo.
    escenarioXML->SetAttribute("ruta_imagen_fondo", this->_ruta_image_fondo.c_str());
    
    // Serializo la lista de actores.
    TiXmlElement * elemento = new TiXmlElement("Actores");

    for (int cur = 0; cur < this->_actores.size(); cur++)
        elemento->LinkEndChild(this->_actores[cur]->aElementoXML());

    escenarioXML->LinkEndChild(elemento);
    
    // Serializo las utilidades.
    elemento = new TiXmlElement("Utilidades");
    
    for (int cur = 0; cur < this->_utilidades.size(); cur++)
        elemento->LinkEndChild(this->_utilidades[cur]->aElementoXML());
    
    escenarioXML->LinkEndChild(elemento);
    
    // Serializo el perimetro.
    escenarioXML->LinkEndChild(this->_perimetro->aElementoXML());
    
    return escenarioXML;
}

void Escenario::deElementoXML (TiXmlElement* pElemento){

    if (strcmp (pElemento->Value(), "Escenario") == 0)
    {
        // Hidrato el path de la imagend e fondo.
        this->_ruta_image_fondo = pElemento->Attribute("ruta_imagen_fondo");
        
        // Hidrato los actores.
        TiXmlElement* elemento = pElemento->FirstChildElement()->FirstChildElement();
        while (NULL != elemento)
        {
            Actor* actor = Actor::deElementoXMLGenerico(elemento);
            if (NULL != actor)
                this->_actores.push_back(actor);
            elemento = elemento->NextSiblingElement();
        }

        // Hidrato la lista de utilidades.
        elemento = pElemento->FirstChildElement()->NextSiblingElement()->FirstChildElement();
        while (elemento != NULL)
        {
            Utilidad* utilidad = Utilidad::deElementoXMLGenerico(elemento);
            if (utilidad)
                this->_utilidades.push_back(utilidad);
            elemento = elemento->NextSiblingElement();
        }
        
        // Hidrato el perimetro.
        this->_perimetro = new Perimetro();
        this->_perimetro->deElementoXML(pElemento->FirstChildElement()->NextSiblingElement()->NextSiblingElement());
    }
}

